#include "BaseCharacter.h"
#include "TileManager.h"
#include "MessagingSystem.h"
#include "Messages\WinTileEventMessage.h"
#include "GamePlayState.h"
#include "AIManager.h"
#include "ParticleManager.h"
#include "TutorialPlayState.h"

BaseCharacter::BaseCharacter(void)
	: BaseInterface(BASECHARACTER)
{
	SetDead(false);
	AniMan = AnimationManager::GetInstance();
	AInfo.currentAnimation = 0;
	AInfo.currentFrame = 0;
	AInfo.fTimeWaited = 0;
	AInfo.bIsFlipped = false;
	AInfo.fScale = 1.0f;
	AInfo.Increment = 1;
	AInfo.prevState = -1;
	AInfo.IsPlaying = true;
	AInfo.Dead = false;
	experience = 0;
	level = 1;
	facingDirection = 2;
	dying = false;
}


BaseCharacter::~BaseCharacter(void)
{
	CSGD_XAudio2* XA = CSGD_XAudio2::GetInstance();
	for(unsigned int i = 0; i < statusEffects.size();i++)
	{
		delete statusEffects[i];
		statusEffects.erase(statusEffects.begin()+i);
		i--;
	}

	for(unsigned int i = 0; i < tileEffects.size();i++)
	{
		delete tileEffects[i];
		tileEffects.erase(tileEffects.begin()+i);
		i--;
	}

	/*if(wpnName != nullptr)
	{
		delete wpnName;
		wpnName = nullptr;
	}

	if(armName != nullptr)
	{
		delete[] armName;
		armName = nullptr;
	}*/

}

bool BaseCharacter::Move(Tile * target, int state)
{
	if(target == nullptr || target->GetObstacle() || target->GetCharacter() != NULL || this->isDead || this->hasMoved || this->usedAction)
		return false;

	int x = 0,y = 0,distance = 0;
	x = this->currentTile->GetX() - target->GetX();
	y = this->currentTile->GetY() - target->GetY();

	if(x < 0)
		x *= -1;
	if(y < 0)
		y*=-1;

	distance = x + y;

	if(distance > this->moveRange)
		return false;
	else
	{
		int sX,sY,bX,bY;

		if(this->currentTile->GetX() > target->GetX())
		{
			sX = target->GetX();
			bX = currentTile->GetX();
		}
		else
		{
			sX = currentTile->GetX();
			bX = target->GetX();
		}
		if(this->currentTile->GetY() > target->GetY())
		{
			sY = target->GetY();
			bY = currentTile->GetY();
		}
		else
		{
			sY = currentTile->GetY();
			bY = target->GetY();
		}

		//numIters = ((bX-sX)+1)*((bY-sY)+1);
		//int numObs = 0;

		TileManager * tm = TileManager::GetInstance();

		/*for(int x = sX;x <= bX;x++)
		{
			for(int y = sY;y <= bY;y++)
			{
				if(x == this->currentTile->GetX() && y == currentTile->GetY())
					continue;

				if(numIters > 4 && ((x == sX && y == bY) || (x == sX && y == sY) || (x == bX && y == bY) || (x == bX && y == sY)))
					continue;
			
				if(numIters == 4&& !((sX == bX)||(sY == bY)))
				{
					if(tm->GetTile(x,y)->GetObstacle() || tm->GetTile(x,y)->GetCharacter() != nullptr)
						numObs++;

					if(numObs >= 2)
						return false;

				}
				else
				{
					if(tm->GetTile(x,y)->GetObstacle() || tm->GetTile(x,y)->GetCharacter() != nullptr)
						return false;
				}
			}
		}*/

		//int newFacing = 0;

		vector<Tile*> tiles;
		tiles.clear();

		if(state == 0)
		if(!GamePlayState::GetInstance()->CheckMoveToTile(this->GetTile(),target,&tiles))
			return false;

		if(state == 1)
			if(!TutorialPlayState::GetInstance()->CheckMoveToTile(this->GetTile(),target,&tiles))
			return false;

		this->currentTile->RemoveEffect();
		for(unsigned int i = 0; i < tileEffects.size();i++)
		{
			delete tileEffects[i];
			tileEffects.erase(tileEffects.begin()+i);
			i--;
		}

		for(unsigned int i = 0; i < tiles.size(); i++)
		{
			this->currentTile->SetCharacter(nullptr);
			//target = currentTile;
			this->currentTile = tiles[i];
			tiles[i]->SetCharacter(this);
			tiles[i]->GetCharacter()->SetTile(tiles[i]);

			this->currentTile->ApplyEffect();
		}

		if(bX-sX > bY-sY)
		{
			if(target->GetX() == bX)
			{
				this->facingDirection = 1;
			}
			else
			{
				this->facingDirection = 3;
			}
		}
		else if(bX-sX < bY-sY)
		{
			if(target->GetY() == bY)
			{
				this->facingDirection = 2;
			}
			else
			{
				this->facingDirection = 0;
			}
		}
		else
		{
			if(target->GetX() == bX)
			{
				this->facingDirection = 1;
			}
			else
			{
				this->facingDirection = 3;
			}
		}

		

		this->hasMoved = true;

		std::string temp = this->GetTile()->GetEventString();

		if(temp == "winCondition")
		{
			WinTileEventMessage * msg = new WinTileEventMessage();
			MessagingSystem::GetInstance()->SendMsg(msg);
		}
		else if(temp == "lossCondition")
		{
			// loss condition code here
		}

		if(type == KNIGHT)
		{
			ChangeState(Knight::KNIGHT_IDLE + facingDirection);
		}

		else if(type == WIZARD)
		{
			ChangeState(Wizard::WIZ_IDLE + facingDirection);
		}

		if(type == ROGUE)
		{
			ChangeState(Rogue::ROGUE_IDLE + facingDirection);
		}

		if(type == ARCHER)
		{
			ChangeState(Archer::ARCH_IDLE + facingDirection);
		}

		if(type == BLACKKNIGHT)
		{
			ChangeState(BlackKnight::BKNIGHT_IDLE + facingDirection);
		}
	}

	/*if((target->GetX() - currentTile->GetX()) <= GetMov() && (target->GetY() - currentTile->GetY()) <= GetMov() && !target->GetObstacle())
	{
		currentTile = target;
	}*/

	TileManager::GetInstance()->ResetHighlights();

	

	return true;
}
bool BaseCharacter::Attack(Tile * target, int state)
{
	if(target->GetCharacter() == nullptr || target->GetCharacter()->GetHP() < 0 || this->usedAction == true || this->IsDead())
		return false;

	if(!this->IsPlayer())
	{
		if(!target->GetCharacter()->IsPlayer())
			return false;
	}
	else
	{
		if(target->GetCharacter()->IsPlayer())
			return false;
	}

	int x = 0,y = 0;
	x = this->currentTile->GetX() - target->GetX();
	y = this->currentTile->GetY() - target->GetY();

	if(x < 0)
		x = -x;
	
	if(y < 0)
		y = -y;

	if(x+y > this->range)
		return false;

	for(unsigned int i = 0; i < target->GetCharacter()->GetStatusEffects()->size();i++)
	{
		if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == COVERED)
		{
			target = (*target->GetCharacter()->GetStatusEffects())[i]->creator->GetTile();
			break;
		}
	}

	bool hidden = false;

	for(unsigned int i = 0; i < target->GetCharacter()->GetStatusEffects()->size();i++)
	{
		if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == HIDDEN)
		{
			hidden = true;
			break;
		}
	}

	bool bridgeBuff = false;
	int bridgeBuffValue = 0;

	for(unsigned int i = 0; i < target->GetCharacter()->GetStatusEffects()->size();i++)
	{
		if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == GUARDING_BRIDGE)
		{
			if(target->GetCharacter()->GetFacing() == 0 && this->GetTile()->GetY() < target->GetY())
			{
				bridgeBuff = true;
				bridgeBuffValue = target->GetCharacter()->GetDef()*2;
				target->GetCharacter()->defense += bridgeBuffValue;
			}
			else if(target->GetCharacter()->GetFacing() == 2 && this->GetTile()->GetY() > target->GetY())
			{
				bridgeBuff = true;
				bridgeBuffValue = target->GetCharacter()->GetDef()*2;
				target->GetCharacter()->defense += bridgeBuffValue;
			}
			else if(target->GetCharacter()->GetFacing() == 1 && this->GetTile()->GetX() > target->GetX())
			{
				bridgeBuff = true;
				bridgeBuffValue = target->GetCharacter()->GetDef()*2;
				target->GetCharacter()->defense += bridgeBuffValue;
			}
			else if(target->GetCharacter()->GetFacing() == 3 && this->GetTile()->GetX() < target->GetX())
			{
				bridgeBuff = true;
				bridgeBuffValue = target->GetCharacter()->GetDef()*2;
				target->GetCharacter()->defense += bridgeBuffValue;
			}
			break;
		}
	}

	if(!hidden)
	{
		int damage = 0;

		if(state == 0)
		{
			damage = GamePlayState::GetInstance()->DiceRoll(this, target->GetCharacter());
			GamePlayState::GetInstance()->SetDamage(damage);
		}

		if(state == 1)
		{
			damage = GamePlayState::GetInstance()->DiceRoll(this, target->GetCharacter(), -1);
			GamePlayState::GetInstance()->SetDamage(damage);
			//damage = TutorialPlayState::GetInstance()->DiceRoll(this, target->GetCharacter());
			//CurAttacker = 
			//TutorialPlayState::GetInstance()->SetDamage(damage);
		}
		
		//target->GetCharacter()->SetHP(target->GetCharacter()->GetHP() - damage);
		// increasing the attacker's exp
		CalculateExp(this, target->GetCharacter(), ATTACK, damage);
	}
	else
		return false;

	if(bridgeBuff)
		target->GetCharacter()->defense -= bridgeBuffValue;

	this->usedAction = true;
	return true;
}
void BaseCharacter::Defend()
{
	StatusEffect * effect = new StatusEffect();
	effect->creator = this;
	effect->effectType = GUARDING;
	effect->effectValue = 10;
	effect->turnsLeft = 2;

	this->defense += effect->effectValue;

	this->statusEffects.push_back(effect);
	this->usedAction = true;
}
bool BaseCharacter::UseItem(Item * selectedItem)
{
	if(selectedItem->ApplyEffect(selectedItem->GetID(), this))
	{
		CalculateExp(this, nullptr, ITEM);
		switch(selectedItem->GetID())
		{
		case HPOTION:
			CSGD_XAudio2::GetInstance()->SFXPlaySound(Game::GetInstance()->GetDrinkID());
			break;
		case MPOTION:
			CSGD_XAudio2::GetInstance()->SFXPlaySound(Game::GetInstance()->GetDrinkID());
			break;
		case INHALER:
			CSGD_XAudio2::GetInstance()->SFXPlaySound(GamePlayState::GetInstance()->GetInhalerID());
			break;
		};
		return true;
	}
	else
		return false;
}
bool BaseCharacter::UseAbility(int abilityID,Tile * target, int state)
{
	if(this->usedAction || this->IsDead())
		return false;

	if(!target)
		return false;

	if(!target->GetCharacter())
		return false;

	if(target->GetCharacter()->GetHP() <=0 || target->GetCharacter()->IsDead())
		return false;

	int x = 0,y = 0;
	x = this->currentTile->GetX() - target->GetX();
	y = this->currentTile->GetY() - target->GetY();

	if(x <0)
		x = -x;
	if(y < 0)
		y = -y;

	int rangeToTarget = x+y;


	switch (abilityID)
	{
	case REINFORCED_CARDBOARD:
		{
			StatusEffect * effect = new StatusEffect();
			effect->creator = this;
			effect->effectType = REINFORCED;
			effect->effectValue = this->level * 4;
			effect->turnsLeft = 2;

			this->statusEffects.push_back(effect);

			this->defense += effect->effectValue;
			this->usedAction = true;
			CalculateExp(this, nullptr, ABILITY);
			CSGD_XAudio2::GetInstance()->SFXPlaySound(GamePlayState::GetInstance()->GetReinforceID());
			return true;
			
			break;
		}
	case SHIELD_BASH:
		{

			if(rangeToTarget != 1)
				return false;

			if(!this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			int dir = -1;

			if(this->currentTile->GetX() - target->GetX() > 0)
				dir = 3;
			else if(this->currentTile->GetX() - target->GetX() < 0)
				dir = 1;
			else if(this->currentTile->GetY() - target->GetY() > 0)
				dir = 0;
			else if(this->currentTile->GetY() - target->GetY() < 0)
				dir = 2;
			else
				return false;

			switch(dir)
			{
			case 0:
				{
					for(int i = 0; i < 2; i++)
					{
						if(TileManager::GetInstance()->GetTile(target->GetX(),target->GetY()-1)->GetObstacle() != true && TileManager::GetInstance()->GetTile(target->GetX(),target->GetY()-1)->GetCharacter() == nullptr)
						{
							BaseCharacter * tarChar = target->GetCharacter();
							target->SetCharacter(nullptr);
							tarChar->SetTile(TileManager::GetInstance()->GetTile(target->GetX(),target->GetY()-1));
							target = tarChar->GetTile();
							target->SetCharacter(tarChar);
							CalculateExp(this, target->GetCharacter(), ABILITY, -1);
							
						}
						else
						{
							if(i == 0)
								return false;
							else
								break;
						}
					}
					this->usedAction = true;
					this->facingDirection = dir;
					ChangeState(Knight::KNIGHT_ABIL1 + facingDirection);

					return true;
					break;
				}
			case 1:
				{
					for(int i = 0; i < 2; i++)
					{
						if(TileManager::GetInstance()->GetTile(target->GetX()+1,target->GetY())->GetObstacle() != true&& TileManager::GetInstance()->GetTile(target->GetX()+1,target->GetY())->GetCharacter() == nullptr)
						{
							BaseCharacter * tarChar = target->GetCharacter();
							target->SetCharacter(nullptr);
							tarChar->SetTile(TileManager::GetInstance()->GetTile(target->GetX()+1,target->GetY()));
							tarChar->GetTile()->SetCharacter(tarChar);
							target = tarChar->GetTile();
							CalculateExp(this, target->GetCharacter(), ABILITY, -1);
						}
						else
						{
							if(i == 0)
								return false;
							else
								break;
						}
					}
					this->usedAction = true;
					this->facingDirection = dir;
					ChangeState(Knight::KNIGHT_ABIL1 + facingDirection);
					return true;
					break;
				}
			case 2:
				{
					for(int i = 0; i < 2; i++)
					{
						if(TileManager::GetInstance()->GetTile(target->GetX(),target->GetY()+1)->GetObstacle() != true && TileManager::GetInstance()->GetTile(target->GetX(),target->GetY()+1)->GetCharacter() == nullptr)
						{
							BaseCharacter * tarChar = target->GetCharacter();
							target->SetCharacter(nullptr);
							tarChar->SetTile(TileManager::GetInstance()->GetTile(target->GetX(),target->GetY()+1));
							target = tarChar->GetTile();
							target->SetCharacter(tarChar);
							CalculateExp(this, target->GetCharacter(), ABILITY, -1);
						}
						else
						{
							if(i == 0)
								return false;
							else
								break;
						}
					}
					this->usedAction = true;
					this->facingDirection = dir;
					ChangeState(Knight::KNIGHT_ABIL1 + facingDirection);
					return true;
					break;
				}
			case 3:
				{
					for(int i = 0; i < 2; i++)
					{
						if(TileManager::GetInstance()->GetTile(target->GetX()-1,target->GetY())->GetObstacle() != true&& TileManager::GetInstance()->GetTile(target->GetX()-1,target->GetY())->GetCharacter() == nullptr)
						{
							BaseCharacter * tarChar = target->GetCharacter();
							target->SetCharacter(nullptr);
							tarChar->SetTile(TileManager::GetInstance()->GetTile(target->GetX()-1,target->GetY()));
							target = tarChar->GetTile();
							target->SetCharacter(tarChar);
							CalculateExp(this, target->GetCharacter(), ABILITY, -1);
						}
						else
						{
							if(i == 0)
								return false;
							else
								break;
						}
					}
					this->usedAction = true;
					this->facingDirection = dir;
					ChangeState(Knight::KNIGHT_ABIL1 + facingDirection);
					return true;
					break;
				}
			}
			break;
		}
	case COVER:
		{
			if(this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			StatusEffect * effect = new StatusEffect();
			effect->creator = this;
			effect->effectType = COVERED;
			effect->effectValue = 0;
			effect->turnsLeft = 2;

			target->GetCharacter()->GetStatusEffects()->push_back(effect);

			this->usedAction = true;

			CalculateExp(this, target->GetCharacter(), ABILITY, -1);
			CSGD_XAudio2::GetInstance()->SFXPlaySound(GamePlayState::GetInstance()->GetGotchaID());
			//ChangeState(Knight::KNIGHT_IDLE + facingDirection);
			return true;
			break;
		}
	case HIDE:
		{
			StatusEffect * effect = new StatusEffect();
			effect->creator = this;
			effect->effectType = HIDDEN;
			effect->effectValue = 0;
			effect->turnsLeft = 2;

			this->statusEffects.push_back(effect);
			this->usedAction = true;

			CalculateExp(this, nullptr, ABILITY);
			CSGD_XAudio2::GetInstance()->SFXPlaySound(GamePlayState::GetInstance()->GetHideID());
			ChangeState(Rogue::ROGUE_HIDE);
			return true;
			break;
		}
	case BACKSTAB:
		{
			if(rangeToTarget!= 1)
				return false;

			if(!this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			int enemyFacing = target->GetCharacter()->GetFacing();
			int damage = GamePlayState::GetInstance()->DiceRoll(this,target->GetCharacter());
			GamePlayState::GetInstance()->SetModifier(0.0f);

			switch(enemyFacing)
			{
			case 0:
				{
					if(this->GetTile()->GetX() == target->GetX())
					{
						if(this->GetTile()->GetY() == target->GetY()+1)
						{
							damage *= 2;
							GamePlayState::GetInstance()->SetModifier(2);
						}
					}
					else
					{
						damage = (int)(damage * 1.5f);
						GamePlayState::GetInstance()->SetModifier(1.5);
					}
					break;

					//ChangeState(Rogue::ROGUE_HIDE);

				}
			case 1:
				{
					if(this->GetTile()->GetY() == target->GetY())
					{
						if(this->GetTile()->GetX() == target->GetX()-1)
						{
							damage *= 2;
							GamePlayState::GetInstance()->SetModifier(2);
						}
					}
					else
					{
						damage = (int)(damage * 1.5f);
						GamePlayState::GetInstance()->SetModifier(1.5);
					}
					break;
				}
			case 2:
				{
					if(this->GetTile()->GetX() == target->GetX())
					{
						if(this->GetTile()->GetY() == target->GetY()-1)
						{
							damage *= 2;
							GamePlayState::GetInstance()->SetModifier(2);
						}
					}
					else
					{
						damage = (int)(damage * 1.5f);
						GamePlayState::GetInstance()->SetModifier(1.5);
					}
					break;
				}
			case 3:
				{
					if(this->GetTile()->GetY() == target->GetY())
					{
						if(this->GetTile()->GetX() == target->GetX()+1)
						{
							damage *= 2;
							GamePlayState::GetInstance()->SetModifier(2);
						}
					}
					else
					{
						damage = (int)(damage * 1.5f);
						GamePlayState::GetInstance()->SetModifier(1.5);
					}
					break;
				}
			};

			for(unsigned int i = 0; i < target->GetCharacter()->GetStatusEffects()->size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == COVERED)
				{
					target = (*target->GetCharacter()->GetStatusEffects())[i]->creator->GetTile();
					break;
				}
			}

			bool hidden = false;

			for(unsigned int i = 0; i < target->GetCharacter()->GetStatusEffects()->size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == HIDDEN)
				{
					hidden = true;
					break;
				}
			}

			if(!hidden)
			{
				//target->GetCharacter()->SetHP(target->GetCharacter()->GetHP() - damage);
				GamePlayState::GetInstance()->SetDamage(damage);
			}

			this->usedAction = true;

			CalculateExp(this, target->GetCharacter(), ABILITY, damage);

			return true;
			break;
		}
	case INFLICT_ALLERGIES:
		{
			if(rangeToTarget!= 1)
				return false;

			if(!this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			StatusEffect * effect = new StatusEffect();
			effect->creator = this;
			effect->effectType = ALLERGIES;
			effect->effectValue = 0;
			effect->turnsLeft = 5;

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == COVERED)
				{
					target = (*target->GetCharacter()->GetStatusEffects())[i]->creator->GetTile();
					break;
				}
			}

			bool hidden = false;

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == HIDDEN)
				{
					hidden = true;
					break;
				}
			}
			if(!hidden)
				target->GetCharacter()->statusEffects.push_back(effect);
			else
				delete effect;

			this->usedAction = true;

			CalculateExp(this, target->GetCharacter(), ABILITY, -1);
			CSGD_XAudio2::GetInstance()->SFXPlaySound(GamePlayState::GetInstance()->GetAllergyID());

			vector<string> stuff = GamePlayState::GetInstance()->GetActiveKeys();

			vector<string>::iterator iter = stuff.begin();

			for( ; iter != stuff.end(); )
			{
				if(iter->find("Allergies.xml") == 0)
				{
					float leftnum1 = (target->GetCharacter()->GetTile()->GetScreenPosX()*TileManager::GetInstance()->GetScale());
					float Topnum1 = (target->GetCharacter()->GetTile()->GetScreenPosY()*TileManager::GetInstance()->GetScale());
					float Rightnum1 = (target->GetCharacter()->GetTile()->GetScreenPosX()*TileManager::GetInstance()->GetScale()) + 64;
					float Bottomnum1 = (target->GetCharacter()->GetTile()->GetScreenPosY()*TileManager::GetInstance()->GetScale()) + 64; 

					ParticleManager::GetInstance()->GetMap()["Allergies.xml"]->SetRectLeft((LONG)leftnum1);
					ParticleManager::GetInstance()->GetMap()["Allergies.xml"]->SetRectTop((LONG)Topnum1);
					ParticleManager::GetInstance()->GetMap()["Allergies.xml"]->SetRectRight((LONG)Rightnum1);
					ParticleManager::GetInstance()->GetMap()["Allergies.xml"]->SetRectBottom((LONG)Bottomnum1);

					ParticleManager::GetInstance()->ResetParticles((*iter));
					iter = stuff.erase(iter);
				}
				else
					iter++;
			}

			float leftnum = (target->GetCharacter()->GetTile()->GetScreenPosX()*TileManager::GetInstance()->GetScale());
			float Topnum = (target->GetCharacter()->GetTile()->GetScreenPosY()*TileManager::GetInstance()->GetScale());
			float Rightnum = (target->GetCharacter()->GetTile()->GetScreenPosX()*TileManager::GetInstance()->GetScale()) + 64;
			float Bottomnum = (target->GetCharacter()->GetTile()->GetScreenPosY()*TileManager::GetInstance()->GetScale()) + 64; 

			ParticleManager::GetInstance()->GetMap()["Allergies.xml"]->SetRectLeft((LONG)leftnum);
			ParticleManager::GetInstance()->GetMap()["Allergies.xml"]->SetRectTop((LONG)Topnum);
			ParticleManager::GetInstance()->GetMap()["Allergies.xml"]->SetRectRight((LONG)Rightnum);
			ParticleManager::GetInstance()->GetMap()["Allergies.xml"]->SetRectBottom((LONG)Bottomnum);
			GamePlayState::GetInstance()->AddToActive("Allergies.xml");
			return true;
			break;
		}
	case LIGHTNING_BOLT:
		{
			if(this->MP < 5)
				return false;

			if(rangeToTarget > this->GetRng())
				return false;

			if(!this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			int damage = 0;

			if(state == 0 )
			{
				damage = GamePlayState::GetInstance()->DiceRoll(this,target->GetCharacter(),LIGHTNING_BOLT);
			}

			if(state == 1 )
			{
				damage = GamePlayState::GetInstance()->DiceRoll(this,target->GetCharacter(),LIGHTNING_BOLT);
				//damage = TutorialPlayState::GetInstance()->DiceRoll(this,target->GetCharacter(),LIGHTNING_BOLT);
			}

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == COVERED)
				{
					target = (*target->GetCharacter()->GetStatusEffects())[i]->creator->GetTile();
					break;
				}
			}

			bool hidden = false;

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == HIDDEN)
				{
					hidden = true;
					break;
				}
			}

			if(!hidden)
			{
				//target->GetCharacter()->SetHP(target->GetCharacter()->GetHP() - damage);

				if(state == 0 )
				GamePlayState::GetInstance()->SetDamage(damage);

				if(state == 1 )
				TutorialPlayState::GetInstance()->SetDamage(damage);
			}
			this->usedAction = true;
			this->MP -= 5;

			CalculateExp(this, target->GetCharacter(), ABILITY, damage);
			return true;
			break;
		}
	case FIRE_BALLS:
		{
			if(this->MP < 10)
				return false;

			if(rangeToTarget > this->GetRng())
				return false;

			if(!this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			int damage = GamePlayState::GetInstance()->DiceRoll(this,target->GetCharacter(),FIRE_BALLS);

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == COVERED)
				{
					target = (*target->GetCharacter()->GetStatusEffects())[i]->creator->GetTile();
					break;
				}
			}

			bool hidden = false;

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == HIDDEN)
				{
					hidden = true;
					break;
				}
			}

			if(!hidden)
			{
				//target->GetCharacter()->SetHP(target->GetCharacter()->GetHP() - damage);
				GamePlayState::GetInstance()->AddToActive("FireBall.xml");
				GamePlayState::GetInstance()->SetDamage(damage);
				GamePlayState::GetInstance()->SetAtkTypeStorage(FIRE_BALLS);
			}
			this->usedAction = true;
			this->MP -= 10;

			CalculateExp(this, target->GetCharacter(), ABILITY, damage);

			return true;
			break;
		}
	case TSUNAMI:
		{
			if(this->MP < 60)
				return false;

			if(rangeToTarget > this->GetRng())
				return false;

			if(!this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			int damage = GamePlayState::GetInstance()->DiceRoll(this,target->GetCharacter(),TSUNAMI);

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == COVERED)
				{
					target = (*target->GetCharacter()->GetStatusEffects())[i]->creator->GetTile();
					break;
				}
			}

			bool hidden = false;

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == HIDDEN)
				{
					hidden = true;
					break;
				}
			}

			if(!hidden)
			{
				//target->GetCharacter()->SetHP(target->GetCharacter()->GetHP() - damage);
				GamePlayState::GetInstance()->AddToActive("TsunamiRight.xml");
				GamePlayState::GetInstance()->SetDamage(damage);
				GamePlayState::GetInstance()->SetAtkTypeStorage(TSUNAMI);
			}
			this->usedAction = true;
			this->MP -= 60;

			CalculateExp(this, target->GetCharacter(), ABILITY, damage);

			return true;
			break;
		}
	case PEROXIDE:
		{
			if(this->MP < 50)
				return false;

			if(rangeToTarget > 1)
				return false;

			if(this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			//int damage = GamePlayState::GetInstance()->DiceRoll(this,target->GetCharacter(),TSUNAMI);
			target->GetCharacter()->SetHP(target->GetCharacter()->GetHP() + 10*this->level);
			GamePlayState::GetInstance()->SetHealing(10*this->level);

			if(target->GetCharacter()->GetHP() > target->GetCharacter()->GetMaxHP())
				target->GetCharacter()->SetHP(target->GetCharacter()->GetMaxHP());

			this->usedAction = true;
			this->MP -= 50;

			CalculateExp(this, target->GetCharacter(), ABILITY, 20*this->level);
			CSGD_XAudio2::GetInstance()->SFXPlaySound(GamePlayState::GetInstance()->GetHealID());
			return true;
			break;
		}
	case MULTI_SHOT:
		{
			if(rangeToTarget > this->range)
				return false;

			if(!this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			int damage = 0;

			GamePlayState::GetInstance()->SetAtkTypeStorage(MULTI_SHOT);

			for(int i = 0; i < 3;i++)
				damage += GamePlayState::GetInstance()->DiceRoll(this,target->GetCharacter());

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == COVERED)
				{
					target = (*target->GetCharacter()->GetStatusEffects())[i]->creator->GetTile();
					break;
				}
			}

			bool hidden = false;

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == HIDDEN)
				{
					hidden = true;
					break;
				}
			}

			if(!hidden)
			{
				damage = (int)(damage * 0.75);
				//target->GetCharacter()->SetHP((int)(target->GetCharacter()->GetHP() - damage));
				GamePlayState::GetInstance()->SetModifier(0.75);
				GamePlayState::GetInstance()->SetDamage(damage);
			}
			this->usedAction = true;

			CalculateExp(this, target->GetCharacter(), ABILITY, damage);

			return true;
			break;
		}
	case SHOOT_HARDER:
		{
			if(rangeToTarget > this->range)
				return false;

			if(!this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			int damage = GamePlayState::GetInstance()->DiceRoll(this,target->GetCharacter());

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == COVERED)
				{
					target = (*target->GetCharacter()->GetStatusEffects())[i]->creator->GetTile();
					break;
				}
			}

			bool hidden = false;

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == HIDDEN)
				{
					hidden = true;
					break;
				}
			}

			if(!hidden)
			{
				//target->GetCharacter()->SetHP((int)(target->GetCharacter()->GetHP() - damage*(1.5*this->level)));
				GamePlayState::GetInstance()->SetDamage((int)(damage *(1.5*this->level)) );
				GamePlayState::GetInstance()->SetModifier(1.5);
				GamePlayState::GetInstance()->SetAtkTypeStorage(SHOOT_HARDER);
			}
			this->usedAction = true;

			CalculateExp(this, target->GetCharacter(), (int)ABILITY, (int)(damage * (1.5 * this->level)));

			return true;
			break;
		}
	case SHOOT_FARTHER:
		{
			if(rangeToTarget > this->range+2)
				return false;

			if(!this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			int damage = GamePlayState::GetInstance()->DiceRoll(this,target->GetCharacter());

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == COVERED)
				{
					target = (*target->GetCharacter()->GetStatusEffects())[i]->creator->GetTile();
					break;
				}
			}

			bool hidden = false;

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == HIDDEN)
				{
					hidden = true;
					break;
				}
			}

			if(!hidden)
			{
				//target->GetCharacter()->SetHP((int)(target->GetCharacter()->GetHP() - damage*0.75));
				GamePlayState::GetInstance()->SetDamage((int)(damage*0.75));
				GamePlayState::GetInstance()->SetModifier(0.75);
				GamePlayState::GetInstance()->SetAtkTypeStorage(SHOOT_FARTHER);
			}
			this->usedAction = true;

			CalculateExp(this, target->GetCharacter(), ABILITY,(int)(damage*0.75f));

			return true;
			break;
		}
	case TAUNT:
		{
			if(rangeToTarget > this->range)
				return false;

			if(!this->IsPlayer())
			{
				if(!target->GetCharacter()->IsPlayer())
					return false;
			}
			else
			{
				if(target->GetCharacter()->IsPlayer())
					return false;
			}

			StatusEffect * effect = new StatusEffect();
			effect->creator = this;
			effect->effectType = TAUNT;
			effect->effectValue = -6;
			effect->turnsLeft = 2;

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == COVERED)
				{
					target = (*target->GetCharacter()->GetStatusEffects())[i]->creator->GetTile();
					break;
				}
			}

			bool hidden = false;

			for(unsigned int i = 0; i < (*target->GetCharacter()->GetStatusEffects()).size();i++)
			{
				if((*target->GetCharacter()->GetStatusEffects())[i]->effectType == HIDDEN)
				{
					hidden = true;
					break;
				}
			}

			if(!hidden)
			{
				target->GetCharacter()->statusEffects.push_back(effect);
				target->GetCharacter()->attack += effect->effectValue;
			}
			else
				delete effect;

			this->usedAction = true;

			CalculateExp(this, target->GetCharacter(), ABILITY, -1);
			int toUse = rand() % 2;
			if(toUse = 0)
				CSGD_XAudio2::GetInstance()->SFXPlaySound(GamePlayState::GetInstance()->GetChickenID());
			else if(toUse = 1)
				CSGD_XAudio2::GetInstance()->SFXPlaySound(GamePlayState::GetInstance()->GetPansyID());

			ChangeState(BlackKnight::BKNIGHT_ABIL1 + facingDirection);

			return true;
			break;
		}
	case BITE_KNEE_CAPS:
		{
			if(this->HP / this->HPMax > 0.25f)
				return false;

			StatusEffect * effect = new StatusEffect();
			effect->creator = this;
			effect->effectType = BITE_KNEE_CAPS;
			effect->effectValue = 2;
			effect->turnsLeft = 9999;

			this->statusEffects.push_back(effect);

			this->attack *= effect->effectValue;

			//this->usedAction = false;
			CalculateExp(this, nullptr, ABILITY);
			CSGD_XAudio2::GetInstance()->SFXPlaySound(GamePlayState::GetInstance()->GetBiteID());
			return true;
			break;
		}
	case GUARD_BRIDGE:
		{
			StatusEffect * effect = new StatusEffect();
			effect->creator = this;
			effect->effectType = GUARD_BRIDGE;
			effect->effectValue = 2;
			effect->turnsLeft = 2;

			this->statusEffects.push_back(effect);

			//this->attack *= effect->effectValue;

			this->usedAction = true;

			CalculateExp(this, nullptr, ABILITY);
			CSGD_XAudio2::GetInstance()->SFXPlaySound(GamePlayState::GetInstance()->GetNoneID());
			return true;
			break;
		}
	case GUARD:
		{
			this->Defend();
			return true;
			break;
		}
	}
	return false;
}
void BaseCharacter::Update(float elapsedTime)
{
	AniMan->Update(this, elapsedTime);
}
void BaseCharacter::Render()
{
	AniMan->Render(this);
}

void BaseCharacter::CalculateExp(BaseCharacter* pUser, BaseCharacter* pTarget, int type, int amt)
{
	unsigned int userLevel;
	unsigned int targLevel;
	unsigned int modifier;

	userLevel = pUser->GetLevel();

	if(pTarget == nullptr)
		targLevel = userLevel;

	else
	targLevel = pTarget->GetLevel();

	modifier = targLevel / userLevel;

	//if(modifier < 1)
	//	modifier = 1;
	switch( type )
	{
	case ATTACK:
		{
			int tester = (10 * modifier);
			if( tester < 1 )
			{
				experience += 1;
				break;
				
			}

			else
			{
				experience += (amt * modifier);
				break;
			}
		
		}

	case ITEM:
		{
			experience += 10;
			break;
		}

	case ABILITY:
		{
			if(pTarget == nullptr)
				experience += 10;

			else if(amt == -1)
			{
				int tester = (10 * modifier);
				if( tester < 1 )
				{
					experience += 1;
					break;
					
				}

				else
				{
					experience += (10 * modifier);
					break;
				}
			}

			else if(amt > 0)
			{
				int tester = (10 * modifier);
				experience += (10 * modifier);
				break;
			}
		}
	};

	

	
}

void BaseCharacter::LevelUp(void)
{
	hpGain = stamina * (3/4) + level;

	level++;

	HP += hpGain;
	MP += mpGain;
	attack += atkGain;
	defense += defGain;
	speed += spdGain;
	agility += agiGain;
	stamina += stmGain;

	experience -= 100;
}

void BaseCharacter::UpdateStatusEffects()
{
	for(unsigned int i = 0; i < this->statusEffects.size();i++)
	{
		statusEffects[i]->turnsLeft--;
		switch(statusEffects[i]->effectType)
		{
		case REINFORCED:
			{
				if(statusEffects[i]->turnsLeft <= 0)
				{
					this->defense -= statusEffects[i]->effectValue;
					delete statusEffects[i];
					statusEffects.erase(statusEffects.begin()+i);
					i--;
				}
				break;
			}
		case COVERED:
			{
				if(statusEffects[i]->turnsLeft <= 0)
				{
					//this->defense -= statusEffects[i]->effectValue;
					delete statusEffects[i];
					statusEffects.erase(statusEffects.begin()+i);
					i--;
				}
				break;
			}
		case HIDDEN:
			{
				if(statusEffects[i]->turnsLeft <= 0)
				{
					//this->defense -= statusEffects[i]->effectValue;
					delete statusEffects[i];
					statusEffects.erase(statusEffects.begin()+i);
					i--;

					ChangeState(Rogue::ROGUE_IDLE + facingDirection);
				}
				break;
			}
		case ALLERGIES:
			{
				if(statusEffects[i]->turnsLeft <= 0)
				{
					//this->defense -= statusEffects[i]->effectValue;
					delete statusEffects[i];
					statusEffects.erase(statusEffects.begin()+i);
					i--;
				}
				else
				{
					this->HP -= 1 * statusEffects[i]->creator->GetLevel();
				}
				break;
			}
		case TAUNTED:
			{
				if(statusEffects[i]->turnsLeft <= 0)
				{
					this->attack -= statusEffects[i]->effectValue;
					delete statusEffects[i];
					statusEffects.erase(statusEffects.begin()+i);
					i--;
				}
				break;
			}
		case KNEE_CAPS:
			{
				if(this->HP / this->HPMax > 0.25f)
				{
					//this->defense -= statusEffects[i]->effectValue;
					this->attack /= statusEffects[i]->effectValue;
					delete statusEffects[i];
					statusEffects.erase(statusEffects.begin()+i);
					i--;
				}
				break;
			}
		case GUARDING_BRIDGE:
			{
				if(statusEffects[i]->turnsLeft <= 0)
				{
					//this->attack -= statusEffects[i]->effectValue;
					delete statusEffects[i];
					statusEffects.erase(statusEffects.begin()+i);
					i--;
				}
				break;
			}
		case GUARDING:
			{
				if(statusEffects[i]->turnsLeft <= 0)
				{
					this->defense -= statusEffects[i]->effectValue;
					delete statusEffects[i];
					statusEffects.erase(statusEffects.begin()+i);
					i--;
				}
				break;
			}
		};
	}
	
	for(unsigned int i = 0; i < this->tileEffects.size();i++)
	{
		if( this->tileEffects[i]->effectType == LAVA_DAMAGE)
			this->HP = this->HP/this->tileEffects[i]->effectValue;
	}

}

void BaseCharacter::SetTile(Tile* t)
{
	//if(currentTile!= nullptr)
		//this->currentTile->RemoveEffect();
	currentTile = t;
	
}


void BaseCharacter::SetWpnName(char* name)				
{ 
	wpnName = name;

	//memcpy_s(wpnName,
}

void BaseCharacter::SetArmName(char* name)				
{ 
	armName = name;
}
